#include <sys/types.h>
#include <sys/socket.h>
#include <semaphore.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

#define PORT htons(7070)
#define C_PORT htons(6060)

#define DATA_SIZE 80
#define BUF_NUMBER 10
#define BACKLOG  10
#define MAX_THREADS 20
#define MAX_INT_NUM 10
#define IP "127.0.0.1"

#define DEG 1
#ifdef DEG 
#define DEBUG(fmt...) printf(fmt)
#endif 

const char *ACQLOCK = "acqlock";
const char *RELLOCK = "rellock";

char *Sever_IPS[3]={"128.6.5.20","128.6.5.81","128.6.5.82"};

typedef struct server_desc_t
{
	char *server_address;
	int server_port;
	int cli_s;
	int active;
} server_desc_t;

typedef struct comm_data_t 
{
	char cmd[DATA_SIZE];
	//char* cmd_obj;
}comm_data_t;

// Initializes a server_desc structure and bring up a connection to the server.
int init_server_desc(server_desc_t *server_desc, char *server_address, int port)
{
	server_desc->server_address = server_address;
	server_desc->server_port = port;

	struct sockaddr_in addr;

	if ((server_desc->cli_s = socket(PF_INET, SOCK_STREAM, 0)) == -1)
			perror("Unable to create socket");
		
	addr.sin_family = PF_INET;
	addr.sin_port = PORT;
	inet_aton(server_address, &addr.sin_addr);

	if (connect(server_desc->cli_s, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1)
	{
	    perror("Unable to connect to server");
	    return -1;
	}
	return 0;
}

// Destroys a server_desc structure and closes a server connection.
int destroy_server_desc(server_desc_t *server_desc)
{
	server_desc->server_address = "";
	server_desc->server_port = 0;
	close(server_desc->cli_s);
	server_desc->cli_s = 0;
}

// This function implements the communication protocol used with the server
// and processes all requests from other functions.
comm_data_t *issue_server_command(server_desc_t *server_desc, comm_data_t* data_in, int timeout)
{
	long count;
	int cont = 1;
	int sendv = 0;
	int recvv = 0;

	comm_data_t *response = malloc(sizeof(comm_data_t));

	do
	{
		// Sends a request out and uses select() to get a response from the server.
		sendv = count = send(server_desc->cli_s, data_in, sizeof(comm_data_t), 0);
		if(sendv == 0)
			printf("ZERO ERROR\n");

		int result;
		fd_set readset;

		struct timeval tv;
		tv.tv_sec = 0;
		tv.tv_usec = 1000*timeout;
		
		struct timeval *tvp;

		if(timeout == 0)
			tvp = NULL;
		else
			tvp = &tv;	

		do
		{
			FD_ZERO(&readset);
			FD_SET(server_desc->cli_s, &readset);
			result = select(server_desc->cli_s + 1, &readset, NULL, NULL, tvp);
		}
		while(result == -1 && errno == EINTR);
		if(result > 0)
		{
			if(FD_ISSET(server_desc->cli_s, &readset))
			{
				result = recv(server_desc->cli_s, response, sizeof(comm_data_t), 0);
				if(result == 0)
				{
					printf("Closing socket...CHECK THIS!\n");
					close(server_desc->cli_s);
				}
			}
		}
		else if(result < 0)
		{
			printf("Select() error: %s\n", strerror(errno));
			exit(-1);
		}

		// Debug code.
		recvv = result;
		int x;
		if(recvv < 20)
			for(x=0; x<1000000000; x++)
				printf("Didnt get back 20, only got back %i\n", recvv);

 	}
	while(recvv <= 0);
    
	DEBUG("response: %s\n", response->cmd);
	return(response);
}


void request_lock();

